package com.sky.myAspect;

import com.sky.annotation.AutoFill;
import com.sky.constant.AutoFillConstant;
import com.sky.context.BaseContext;
import com.sky.enumeration.OperationType;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.time.LocalDateTime;

@Component
@Aspect
@Slf4j
public class MyAspect {

    @Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)")
    public void pt() {
    }

    @Before("pt()")
    public void AutoFill(JoinPoint joinPoint) throws Exception {
        log.info("AutoFill..............");


        //1 判断原始方法参数是否为null,如果为null直接结束
        Object[] entitys = joinPoint.getArgs();
        if (entitys == null || entitys.length == 0) {
            return;
        }

        //2 获取方法上注解
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();//方法签名对象
        Method method = signature.getMethod();//获取方法
        AutoFill autoFill = method.getAnnotation(AutoFill.class);//获取方法上注解

        //3   判断方法上注解中的属性是插入操作还是更新操作
        //3.1 准备参数插入操作或更新操作自动填充字段
        LocalDateTime localDateTime = LocalDateTime.now();//创建时间 修改时间
        Long currentId = BaseContext.getCurrentId();//创建人 修改人
        OperationType value = autoFill.value();

        //3.2 调用反射设置参数
        //判断填充的字段是插入操作还是更新操作
        Object entity = entitys[0];//获取对象
        Class<?> aClass = entity.getClass();//获取对象字节码
        if (value.equals(OperationType.INSERT)) {
            //插入操作,填充创建时间 修改时间 创建人 修改人字段
            //反射获取成员方法
            Method setCreateTime = aClass.getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);
            Method setUpdateTime = aClass.getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
            Method setUpdateUser = aClass.getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);
            Method setCreateUser = aClass.getDeclaredMethod(AutoFillConstant.SET_CREATE_USER, Long.class);
            //反射设置属性值
            setCreateTime.invoke(entity,localDateTime);
            setUpdateTime.invoke(entity,localDateTime);
            setCreateUser.invoke(entity,currentId);
            setUpdateUser.invoke(entity,currentId);
        } else {
            //修改操作,填充修改时间 修改人字段
            Method setUpdateTime = aClass.getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
            Method setUpdateUser = aClass.getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);
            setUpdateTime.invoke(entity, localDateTime);
            setUpdateUser.invoke(entity, currentId);
        }
    }
}
